package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
)

var db *sql.DB

func main() {
	// 初始化数据库连接
	var err error
	db, err = sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/stock?parseTime=true")
	if err != nil {
		log.Fatal("数据库连接失败:", err)
	}
	defer db.Close()

	// 测试数据库连接
	err = db.Ping()
	if err != nil {
		log.Fatal("数据库连接测试失败:", err)
	}

	r := mux.NewRouter()

	// 设置API路由
	r.HandleFunc("/api/zdfenbu", getZdfenbuData).Methods("GET")
	r.HandleFunc("/api/zdtcount", getZdtcountData).Methods("GET")
	r.HandleFunc("/api/fbfailed", getFbfailedData).Methods("GET")
	r.HandleFunc("/api/ztpool", getZtpoolData).Methods("GET")
	r.HandleFunc("/api/yes_ztpool", getYesZtpoolData).Methods("GET")
	r.HandleFunc("/api/gn_top10", getGnTop10Data).Methods("GET")

	fs := http.FileServer(http.Dir("../static"))
	r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))

	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "../static/index.html")
	})

	fmt.Println("Server is running on port 8080...")
	http.ListenAndServe(":8080", r)

}

// 以下是各个API处理函数的占位符
func getZdfenbuData(w http.ResponseWriter, r *http.Request) {
	log.Printf("收到请求: %s %s", r.Method, r.URL.Path)
	date := r.URL.Query().Get("date")
	if date == "" {
		date = time.Now().Format("20060102")
	}

	rows, err := db.Query(`
		SELECT keyint, value 
		FROM zdfenbu 
		WHERE qdate = ? 
		ORDER BY keyint`, date)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	type ZdfenbuItem struct {
		Range int `json:"range"`
		Count int `json:"count"`
	}

	var results []ZdfenbuItem
	for rows.Next() {
		var keyint, value int
		if err := rows.Scan(&keyint, &value); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		results = append(results, ZdfenbuItem{Range: keyint, Count: value})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(results)
}

func getZdtcountData(w http.ResponseWriter, r *http.Request) {
	log.Printf("收到请求: %s %s", r.Method, r.URL.Path)
	date := r.URL.Query().Get("date")
	if date == "" {
		date = time.Now().Format("20060102")
	}

	rows, err := db.Query(`
		SELECT t, ztc, dtc 
		FROM zdtcount 
		WHERE qdate = ? 
		ORDER BY t`, date)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	type ZdtcountItem struct {
		Time      string `json:"time"`
		UpLimit   int    `json:"upLimit"`
		DownLimit int    `json:"downLimit"`
	}

	var results []ZdtcountItem
	for rows.Next() {
		var t, ztc, dtc int
		if err := rows.Scan(&t, &ztc, &dtc); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// 格式化时间为HH:MM
		timeStr := fmt.Sprintf("%02d:%02d", t/100, t%100)
		results = append(results, ZdtcountItem{
			Time:      timeStr,
			UpLimit:   ztc,
			DownLimit: dtc,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(results)
}

func getFbfailedData(w http.ResponseWriter, r *http.Request) {
	log.Printf("收到请求: %s %s", r.Method, r.URL.Path)
	date := r.URL.Query().Get("date")
	if date == "" {
		date = time.Now().Format("20060102")
	}

	rows, err := db.Query(`
		SELECT t, c, zbp 
		FROM fbfailed 
		WHERE qdate = ? 
		ORDER BY t`, date)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	type FbfailedItem struct {
		Time        string  `json:"time"`
		Count       int     `json:"count"`
		FailedRatio float64 `json:"failedRatio"`
	}

	var results []FbfailedItem
	for rows.Next() {
		var t, c int
		var zbp float64
		if err := rows.Scan(&t, &c, &zbp); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		// 格式化时间为HH:MM
		timeStr := fmt.Sprintf("%02d:%02d", t/100, t%100)
		results = append(results, FbfailedItem{
			Time:        timeStr,
			Count:       c,
			FailedRatio: zbp,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(results)
}

func getZtpoolData(w http.ResponseWriter, r *http.Request) {
	log.Printf("收到请求: %s %s", r.Method, r.URL.Path)
	date := r.URL.Query().Get("date")
	if date == "" {
		date = time.Now().Format("20060102")
	}

	rows, err := db.Query(`
		SELECT code, name, price, change_pct, amount, ltsz, tshare, hs, lbc, 
		       fbt, lbt, fund, zbc, hybk, zttj_days, zttj_ct, market
		FROM ztpool 
		WHERE qdate = ?`, date)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	type ZtpoolItem struct {
		Code      string  `json:"code"`
		Name      string  `json:"name"`
		Price     float64 `json:"price"`
		ChangePct float64 `json:"changePct"`
		Amount    int64   `json:"amount"`
		Ltsz      float64 `json:"ltsz"`
		Tshare    float64 `json:"tshare"`
		Hs        float64 `json:"hs"`
		Lbc       int     `json:"lbc"`
		Fbt       string  `json:"fbt"`
		Lbt       string  `json:"lbt"`
		Fund      float64 `json:"fund"`
		Zbc       int     `json:"zbc"`
		Hybk      string  `json:"hybk"`
		ZttjDays  int     `json:"zttjDays"`
		ZttjCt    int     `json:"zttjCt"`
		Market    int     `json:"market"`
	}

	var results []ZtpoolItem
	for rows.Next() {
		var code, name, hybk string
		var price, change_pct, ltsz, tshare, hs, fund float64
		var amount int64
		var lbc, fbt, lbt, zbc, zttj_days, zttj_ct, market int

		if err := rows.Scan(&code, &name, &price, &change_pct, &amount, &ltsz, &tshare, &hs, &lbc,
			&fbt, &lbt, &fund, &zbc, &hybk, &zttj_days, &zttj_ct, &market); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// 格式化时间为HH:MM
		fbtStr := fmt.Sprintf("%02d:%02d", fbt/100, fbt%100)
		lbtStr := fmt.Sprintf("%02d:%02d", lbt/100, lbt%100)

		results = append(results, ZtpoolItem{
			Code:      code,
			Name:      name,
			Price:     price,
			ChangePct: change_pct,
			Amount:    amount,
			Ltsz:      ltsz,
			Tshare:    tshare,
			Hs:        hs,
			Lbc:       lbc,
			Fbt:       fbtStr,
			Lbt:       lbtStr,
			Fund:      fund,
			Zbc:       zbc,
			Hybk:      hybk,
			ZttjDays:  zttj_days,
			ZttjCt:    zttj_ct,
			Market:    market,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(results)
}

func getYesZtpoolData(w http.ResponseWriter, r *http.Request) {
	log.Printf("收到请求: %s %s", r.Method, r.URL.Path)
	date := r.URL.Query().Get("date")
	if date == "" {
		date = time.Now().Format("20060102")
	}

	rows, err := db.Query(`
		SELECT code, name, price, change_pct, amount, ltsz, tshare, hs, 
		       yfbt, ylbc, hybk, zttj_days, zttj_ct, market
		FROM yes_ztpool 
		WHERE qdate = ?`, date)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	type YesZtpoolItem struct {
		Code      string  `json:"code"`
		Name      string  `json:"name"`
		Price     float64 `json:"price"`
		ChangePct float64 `json:"changePct"`
		Amount    int64   `json:"amount"`
		Ltsz      float64 `json:"ltsz"`
		Tshare    float64 `json:"tshare"`
		Hs        float64 `json:"hs"`
		Yfbt      string  `json:"yfbt"`
		Ylbc      int     `json:"ylbc"`
		Hybk      string  `json:"hybk"`
		ZttjDays  int     `json:"zttjDays"`
		ZttjCt    int     `json:"zttjCt"`
		Market    int     `json:"market"`
	}

	var results []YesZtpoolItem
	for rows.Next() {
		var code, name, hybk string
		var price, change_pct, ltsz, tshare, hs float64
		var amount int64
		var yfbt, ylbc, zttj_days, zttj_ct, market int

		if err := rows.Scan(&code, &name, &price, &change_pct, &amount, &ltsz, &tshare, &hs,
			&yfbt, &ylbc, &hybk, &zttj_days, &zttj_ct, &market); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		// 格式化时间为HH:MM
		yfbtStr := fmt.Sprintf("%02d:%02d", yfbt/100, yfbt%100)

		results = append(results, YesZtpoolItem{
			Code:      code,
			Name:      name,
			Price:     price,
			ChangePct: change_pct,
			Amount:    amount,
			Ltsz:      ltsz,
			Tshare:    tshare,
			Hs:        hs,
			Yfbt:      yfbtStr,
			Ylbc:      ylbc,
			Hybk:      hybk,
			ZttjDays:  zttj_days,
			ZttjCt:    zttj_ct,
			Market:    market,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(results)
}

func getGnTop10Data(w http.ResponseWriter, r *http.Request) {
	log.Printf("收到请求: %s %s", r.Method, r.URL.Path)
	date := r.URL.Query().Get("date")
	if date == "" {
		date = time.Now().Format("20060102")
	}

	rows, err := db.Query(`
		SELECT board_code, board_name, board_type, price, change_percent, 
		       turnover_rate, total_market_value, rising_count, falling_count,
		       top_stock_name, top_stock_rise, top_stock_code, f141,
		       lowest_stock_name, lowest_stock_code, f209, lowest_stock_percent
		FROM gn_top10 
		WHERE qdate = ?`, date)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer rows.Close()

	type GnTop10Item struct {
		BoardCode          string  `json:"boardCode"`
		BoardName          string  `json:"boardName"`
		BoardType          int     `json:"boardType"`
		Price              float64 `json:"price"`
		ChangePercent      float64 `json:"changePercent"`
		TurnoverRate       float64 `json:"turnoverRate"`
		TotalMarketValue   int64   `json:"totalMarketValue"`
		RisingCount        int     `json:"risingCount"`
		FallingCount       int     `json:"fallingCount"`
		TopStockName       string  `json:"topStockName"`
		TopStockRise       float64 `json:"topStockRise"`
		TopStockCode       string  `json:"topStockCode"`
		TopStockMarket     int     `json:"topStockMarket"`
		LowestStockName    string  `json:"lowestStockName"`
		LowestStockCode    string  `json:"lowestStockCode"`
		LowestStockMarket  int     `json:"lowestStockMarket"`
		LowestStockPercent float64 `json:"lowestStockPercent"`
	}

	var results []GnTop10Item
	for rows.Next() {
		var boardCode, boardName, topStockName, topStockCode, lowestStockName, lowestStockCode string
		var boardType, risingCount, fallingCount, f141, f209 int
		var price, changePercent, turnoverRate, topStockRise, lowestStockPercent float64
		var totalMarketValue int64

		if err := rows.Scan(&boardCode, &boardName, &boardType, &price, &changePercent,
			&turnoverRate, &totalMarketValue, &risingCount, &fallingCount,
			&topStockName, &topStockRise, &topStockCode, &f141,
			&lowestStockName, &lowestStockCode, &f209, &lowestStockPercent); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		results = append(results, GnTop10Item{
			BoardCode:          boardCode,
			BoardName:          boardName,
			BoardType:          boardType,
			Price:              price,
			ChangePercent:      changePercent,
			TurnoverRate:       turnoverRate,
			TotalMarketValue:   totalMarketValue,
			RisingCount:        risingCount,
			FallingCount:       fallingCount,
			TopStockName:       topStockName,
			TopStockRise:       topStockRise,
			TopStockCode:       topStockCode,
			TopStockMarket:     f141,
			LowestStockName:    lowestStockName,
			LowestStockCode:    lowestStockCode,
			LowestStockMarket:  f209,
			LowestStockPercent: lowestStockPercent,
		})
	}

	w.Header().Set("Content-Type", "application/json")
	json.NewEncoder(w).Encode(results)
}
